<?php
class MagicDemo {
    private $data = [];
    
    // 构造函数，创建对象时调用
    public function __construct() {
        echo "对象被创建了\n";
    }
    
    // 析构函数，对象被销毁时调用
    public function __destruct() {
        echo "对象被销毁了\n";
    }
    
    // 当访问不存在或私有属性时调用
    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }
    
    // 当设置不存在或私有属性时调用
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
    
    // 当检查不存在或私有属性是否设置时调用
    public function __isset($name) {
        return isset($this->data[$name]);
    }
    
    // 当删除不存在或私有属性时调用
    public function __unset($name) {
        unset($this->data[$name]);
    }
    
    // 当调用不存在或私有方法时调用
    public function __call($name, $arguments) {
        echo "调用了不存在的方法：{$name}，参数：" . implode(', ', $arguments) . "\n";
    }
    
    // 当调用不存在或私有静态方法时调用
    public static function __callStatic($name, $arguments) {
        echo "调用了不存在的静态方法：{$name}，参数：" . implode(', ', $arguments) . "\n";
    }
    
    // 当对象被当作字符串使用时调用
    public function __toString() {
        return "这是一个MagicDemo对象的字符串表示";
    }
    
    // 当对象被序列化时调用
    public function __sleep() {
        // 返回需要被序列化的属性名称数组
        return ['data'];
    }
    
    // 当对象被反序列化时调用
    public function __wakeup() {
        echo "对象被反序列化了\n";
    }
    
    // 当使用var_dump()或print_r()输出对象时调用
    public function __debugInfo() {
        return [
            'data_count' => count($this->data),
            'data_keys' => array_keys($this->data)
        ];
    }
}

// 使用魔术方法
$obj = new MagicDemo();

// __set
$obj->name = "张三";
$obj->age = 25;

// __get
echo "姓名：" . $obj->name . "\n";

// __isset
echo "age是否设置：" . (isset($obj->age) ? "是" : "否") . "\n";

// __unset
unset($obj->age);
echo "age是否设置：" . (isset($obj->age) ? "是" : "否") . "\n";

// __call
$obj->notExistMethod("参数1", "参数2");

// __callStatic
MagicDemo::notExistStaticMethod("静态参数");

// __toString
echo $obj . "\n";

// __debugInfo
var_dump($obj);

// __sleep和__wakeup
$serialized = serialize($obj);
echo "序列化结果：" . $serialized . "\n";
$unserialized = unserialize($serialized);
?>